home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / MiscKit1.7.1 / MiscKit / Palettes / MiscDragViews / MiscViews.subproj / MiscIconWell.m < prev    next >
Encoding:
Text File  |  1995-04-12  |  12.3 KB  |  467 lines

  1. /***************************************************************************
  2.  * CLASS:        MiscIconWell
  3.  * Copyright (C) 1995 Robert Todd Thomas
  4.  * Use is governed by the MiscKit license
  5.  *
  6.  *    See the header file for more information.
  7.  *
  8.  * This object is included in the MiscKit by permission from the author
  9.  * and its use is governed by the MiscKit license, found in the file
  10.  * "LICENSE.rtf" in the MiscKit distribution.  Please refer to that file
  11.  * for a list of all applicable permissions and restrictions.
  12.  ***************************************************************************/
  13.  
  14. #import <misckit/MiscString.h>        // here for backward compatibility
  15. #import "MiscIconWell.h"
  16.  
  17. /*
  18.  * A proper implementation of versioning. If you add ivars to the class (or
  19.  * just want to dork with the reading/writing) check out the comments tagged
  20.  * "Archiving: READ ME". BJM 5/24/94
  21.  */
  22.  
  23. /*
  24.  * **** Archiving: READ ME **** This is the current and defined version of the
  25.  * class. It is used to identify what data will be written and how that will
  26.  * happen. If the read/write stuff is modified AT ALL, this must be bumped up
  27.  * (I always bump by one) and the other comments must be followed. Failure to
  28.  * do so will result in palettes and nibs that cannot be read. BJM 5/24/94
  29.  */
  30. #define MISC_ICON_WELL_VERSION 1
  31.  
  32. @implementation MiscIconWell
  33.  
  34. + initialize
  35. {
  36.     if (self == [MiscIconWell class]) 
  37.     {
  38.         /*
  39.          * **** Archiving: READ ME **** After bumping the _VERSION, it is
  40.          * considered common practice to add a comment line indicating the new
  41.          * version number, date, and modifier. Optionally, the reason for the
  42.          * change. There is no need to modify the setVersion message. BJM
  43.          * 5/24/94 
  44.          */
  45.         // version 0: initial.  (bjm)
  46.            [[MiscIconWell class] setVersion:MISC_ICON_WELL_VERSION];
  47.     }
  48.     
  49.     return self;
  50. }
  51.  
  52.  
  53.  
  54. - initFrame: (const NXRect *)frameRect
  55. {
  56.       [super initFrame: frameRect];
  57.  
  58.     filename = NULL;    
  59.     [self setAllowDoubleClickLaunch: YES];
  60.     return self;
  61. }
  62.  
  63.  
  64.  
  65. - initDragTypes
  66. {    
  67.     // Register to accept drags that are on the NXFilenamePboard.
  68.       const char *const types[] = {NXFilenamePboardType};
  69.   
  70.     [self registerForDraggedTypes: (const char *const *)&types count: 1];
  71.     return self;
  72. }
  73.  
  74.  
  75.     
  76. - free
  77. {
  78.     if (filename)
  79.         NX_FREE (filename);
  80.  
  81.     return [super free];
  82. }
  83.  
  84.  
  85.  
  86. - (const char *)filename
  87. {   
  88.     // Returns the filename that the view currently represents. If the view is
  89.     // empty, NULL is returned.
  90.     return (const char *)filename;
  91. }
  92.  
  93.  
  94.  
  95. - setImage: (NXImage *)anImage
  96. {
  97.     // Overidden from MiscDragView since you could potentially set anImage
  98.     // to nil which would erase what was contained in the view. Therefore
  99.     // we should check for that and free the filename if there is no image.
  100.  
  101.     [super setImage: anImage];
  102.     
  103.     if ([self image] == nil)
  104.         if (filename && (strlen(filename)))
  105.         {
  106.             NX_FREE (filename);
  107.             filename = NULL;
  108.          }
  109.     return self;
  110. }
  111.  
  112.  
  113.  
  114. - setImageByFilename: (const char *)aFilename
  115. {
  116.     // Overridden from MiscDragView so the icon representation of the file
  117.     // is fetched instead of the image itself (likely the filename is not
  118.     // an image). It also has a small hack that if there are more than one
  119.     // filename that it steals that multiple.tiff from Librarian.app. 
  120.  
  121.     // Passing aFilename as NULL essentially erases the image in the view.
  122.     if (aFilename == NULL)
  123.         return [super setImageByFilename: NULL];
  124.     
  125.     if (filename && strlen(filename))
  126.         NX_FREE (filename);
  127.      
  128.     filename = NX_MALLOC (filename, char, strlen(aFilename)+1);
  129.     strcpy (filename, aFilename);
  130.     
  131.     /*
  132.      * Multiple filenames are separated by tabs. We can't use -numWords because
  133.      * numWords checks for any NXIsSpace which includes spaces. Result: if we
  134.      * use numWords, it treats any filename with spaces as "multiple". BJM
  135.      * 5/24/94    
  136.      */
  137.     if (index([self filename], '\t') != NULL)
  138.         [super setImageByFilename: "/NextApps/Librarian.app/multiple.tiff"];
  139.     else    
  140.         [self setImage: [ [Application workspace] getIconForFile: aFilename] ];
  141.     
  142.     return self;
  143. }
  144.  
  145.  
  146.  
  147. - setAllowDoubleClickLaunch: (BOOL)aBool
  148. {
  149.     allowDoubleClickLaunch = aBool;
  150.     return self;
  151. }
  152.  
  153.  
  154.  
  155. - (BOOL)allowDoubleClickLaunch
  156. {
  157.     return allowDoubleClickLaunch;
  158. }
  159.  
  160.  
  161.  
  162. - launch:sender
  163. {
  164.     // Launch/open file in WS: BJM 5/24/94
  165.     // Did not work for launching multiple files under 3.0 (and possilbly 3.x)
  166.     // and was fixed by Stephen Fitzpatrick 07/17/94.
  167.  
  168.     NXPoint   p;
  169.     
  170.     // p is supposed to be the location of the image:
  171.     // I'm not sure what value it should be set to.
  172.     p = bounds.origin;
  173.     
  174.     if (index([self filename], '\t'))
  175.     {
  176.         // Multiple files.
  177.         // Make a copy of the string, and iterate through each filename,         
  178.         // replacing tabs with NULLs.
  179.         
  180.         char    *start, *end;
  181.         int    length = strlen ([self filename]);
  182.         char    copy[length+1];
  183.         
  184.         strcpy(copy, [self filename]);
  185.         start = copy;
  186.     
  187.         // Open the first file with animation.
  188.         end = index(start, '\t');
  189.         *end = '\0';
  190.         
  191.         // causes the animation of the icon
  192.         [[Application workspace]
  193.                 openFile:start
  194.                 fromImage:[self image] at:&p inView:self
  195.         ];
  196.         start = end+1;
  197.         
  198.         // Now do the rest of the files without animation.
  199.         do
  200.         {
  201.             end = index(start, '\t');
  202.             if (end)
  203.             {
  204.                 *end = '\0';
  205.                 [[Application workspace] openFile:start];
  206.                 start = end+1;
  207.             }
  208.             else // The last file.
  209.                 [[Application workspace] openFile:start];
  210.         }
  211.         while (end);
  212.     }
  213.     else
  214.     {
  215.         // There's only one file: open it with animation.
  216.         [[Application workspace]
  217.                 openFile: [self filename]
  218.                 fromImage:[self image] at:&p inView:self
  219.         ];
  220.     }
  221.     
  222.     return self;
  223. }
  224.  
  225.  
  226.  
  227. - mouseDown: (NXEvent *)theEvent
  228. {
  229.     // Override mouseDown to check if the icon was double clicked. If so, then
  230.     // launch it from workspace, else let super handle it.
  231.  
  232.     /*
  233.      * Only attempt to open file if there (1) DC is allowed, (2) this is a DC
  234.      * event, and (3) there is a file to open. BJM 5/24/94
  235.      */
  236.     if ([self allowDoubleClickLaunch] && theEvent->data.mouse.click == 2)
  237.         if (filename != NULL && strlen(filename) > 0)
  238.             return [self launch:self];
  239.         
  240.     [super mouseDown: theEvent];
  241.     return self;
  242. }
  243.  
  244.  
  245.  
  246. - calculateDragPoint: (NXPoint *)dragPoint andOffset: (NXPoint *)offset
  247. {
  248.     // Make the dragPoint be the middle of the image, so it looks nice. This
  249.     // is overridden from MiscDragView.
  250.  
  251.     dragPoint->x -= imageSize.width/2.0;
  252.     dragPoint->y -= imageSize.width/2.0;
  253.     return self;
  254. }
  255.  
  256.  
  257.     
  258. - (BOOL)setupForSourceDrag
  259. {
  260.     // Put the data on the pasteboard when a source drag takes place, and
  261.     // also choose the image to drag. 
  262.     // ...only if there is something to drag... BJM 5/24/94
  263.  
  264.     if (filename != NULL && strlen(filename) > 0) 
  265.     {
  266.           id  dragPB = [self draggingPasteboard];
  267.       
  268.         [dragPB declareTypes:&NXFilenamePboardType num:1 owner:self];        
  269.         [dragPB writeType: NXFilenamePboard 
  270.             data: [self filename] 
  271.             length: strlen([self filename]) ];
  272.             
  273.         [self setDragImage: theImage];
  274.         return YES;
  275.     }
  276.     return NO;
  277. }
  278.  
  279.  
  280.  
  281. - (BOOL)performDragOperation: sender
  282. {
  283.     // Check if an incoming dragged icon is using the NXFilenamePboardType. If
  284.     // not, then don't accept the drag.
  285.  
  286.     id  dragPB = [self draggingPasteboard];
  287.       char  *pbData;
  288.       int  pbLength;
  289.  
  290.     if ([dragPB readType: NXFilenamePboardType data: &pbData 
  291.             length: &pbLength] == nil)
  292.     {
  293.         // If you are ending the drag, make sure to clean up.
  294.         [self cleanupAfterDestinationDrag];
  295.         return NO;    
  296.      }
  297.      
  298.     return YES;
  299. }
  300.  
  301.  
  302.  
  303. - concludeDragOperation: sender
  304. {
  305.     // Take the data from the pasteboard and set the new image.
  306.  
  307.       id  dragPB = [self draggingPasteboard];
  308.       char  *pbData;
  309.       int  pbLength;
  310.   
  311.     [dragPB readType: NXFilenamePboardType data: &pbData 
  312.             length: &pbLength];
  313.     [self setImageByFilename: pbData];
  314.     [dragPB deallocatePasteboardData: pbData length: pbLength];
  315.  
  316.     // Make sure to call super's implementation.
  317.     [super concludeDragOperation: sender];
  318.     return self;
  319. }
  320.  
  321.  
  322.  
  323. /*********** Archiving *************/
  324.  
  325. - read:(NXTypedStream *)stream
  326. {
  327.     int version;
  328.     id  oldfilename;
  329.  
  330.     [super read:stream];
  331.     
  332.     version = NXTypedStreamClassVersion(stream, "MiscIconWell");
  333.         
  334.     /*
  335.      * **** Archiving: READ ME **** This code (and its analogue in write:) is
  336.      * critical. When you bump MISC_ICON_WELL_VERSION, copy the whole _current_
  337.      * case ("case MISC_ICON_WELL_VERSION: ... break;"), and duplicate it.
  338.      * Change the "MISC_ICON_WELL_VERSION" in the old case to the OLD
  339.      * (pre-bump) version number. Now, dork the "new current" version into
  340.      * whatever you want. See how this code can now read EITHER version out of
  341.      * the typed stream?
  342.      *
  343.      * If you are adding yet another version, leave the previous versionS in
  344.      * place. That way you can still read archived objects that are more than
  345.      * one version old. Don't forget to take whatever actions are necessary to
  346.      * harmonize those old values. For example, if you converted an "int" ivar
  347.      * to "double", you'd need to (in the old version) to read the int version
  348.      * into a temp variable, and convert it in to the double var. BJM 5/24/94
  349.      */
  350.     switch (version)
  351.     {
  352.     // filename used to be a string object
  353.     case 0:
  354.         oldfilename = NXReadObject (stream);
  355.         if (oldfilename)
  356.         {
  357.             NX_MALLOC (filename, char, [oldfilename length]+1);
  358.             strcpy (filename, [oldfilename stringValue]);
  359.             
  360.             [oldfilename free];
  361.          }
  362.              
  363.         NXReadTypes (stream, "c", &allowDoubleClickLaunch);
  364.         break;
  365.  
  366.     case MISC_ICON_WELL_VERSION:
  367.         NXReadTypes (stream, "*c", 
  368.                         &filename, &allowDoubleClickLaunch);
  369.         break;
  370.  
  371.     default:
  372.         NXLogError("[%s %s] - unknown version of %s in typed stream",
  373.             [[self class] name], sel_getName(_cmd), [[self class] name]);
  374.         break;
  375.     }
  376.  
  377.     return self;
  378. }
  379.  
  380. - write:(NXTypedStream *)stream
  381. {
  382.   id  oldfilename = nil;
  383.   
  384.     [super write:stream];
  385.     
  386.     /*
  387.      * **** Archiving: READ ME **** Home stretch. Now (just like read:)
  388.      * duplicate the current case ("case MISC_ICON_WELL_VERSION: ... break;").
  389.      * Once again, change the "MISC_ICON_WELL_VERSION" of the first one to the
  390.      * OLD version number. Now adjust the new/current MISC_ICON_WELL_VERSION
  391.      * (remember, you've bumped it) to the new way of writing vars. See how
  392.      * this code (because the constant is in the switch statement) always
  393.      * writes out ONLY the current version, but leaves the old version(s)
  394.      * around to posterity. DO NOT DELETE THE OLD VERSIONS. Leave them to
  395.      * clutter up the world. BJM 5/24/94  
  396.      */
  397.     switch (MISC_ICON_WELL_VERSION)
  398.     {
  399.     case 0:
  400.         NXWriteObject(stream, oldfilename);
  401.         NXWriteTypes (stream, "c", &allowDoubleClickLaunch);
  402.         break;
  403.  
  404.     case MISC_ICON_WELL_VERSION:
  405.         NXWriteTypes (stream, "*c", &filename, &allowDoubleClickLaunch);
  406.         break;
  407.  
  408.     default:
  409.         NXLogError("[%s %s] - unknown version of %s in typed stream",
  410.             [[self class] name], sel_getName(_cmd), [[self class] name]);
  411.         break;
  412.     }
  413.  
  414.     return self;
  415. }
  416.  
  417. /*
  418.  * Methods to support a stringValue - basically our filename, handled
  419.  * just like stringValue in Control objects.  (This change didn't involve
  420.  * adding any ivars or any dorking with reading/writing, so for now I've
  421.  * left the class version number alone.)
  422.  * shayman
  423.  * Aug 2 1994
  424.  */
  425. - (const char *)stringValue
  426. {
  427.     return [self filename];
  428. }
  429. - setStringValue:(const char *)aValue
  430. {
  431.     return [self setImageByFilename:aValue];
  432. }
  433. - takeStringValueFrom:sender
  434. {
  435.     if ( [sender respondsTo:@selector(stringValue)] )
  436.     return [self setStringValue: [sender stringValue]];
  437.     return nil;
  438. }
  439.  
  440. @end
  441.  
  442.  
  443. /***************************************************************************
  444.   CHANGES:
  445.   
  446.   Small bug fixes: BJM 5/24/94 (Bruce McKenzie, spuds@netcom.com)
  447.     1) changed "- (char *)filename" to "- (const char *)filename"
  448.     2) fixed recognition of multiple files in filename to look for tab,
  449.         rather than "any whitespace".
  450.     3) fixed places where it was assumed that filename ivar was ever nil
  451.     4) Added proper archiving/versioning to class.
  452.     5) Added "- launch:sender" method
  453.   Small fix: 07/18/94(Stephen Fitzpatrick, sfitzp@elegabalus.cs.qub.ac.uk)
  454.      6) launch: sender did not launch multiple files (under 3.0), but does now
  455.   Todd Thomas (todd@avocado.supernet.ab.ca) on September 20, 1994
  456.       7) Removed the MiscString instance so it would have less dependencies
  457.         when palettized.
  458.     8) Overrode setImage from MiscDragView since it may be nil and the
  459.         current filename should be freed and set to NULL.
  460.   General small bug fixes (v1.4) (Todd)
  461.       9) With the changes to the MiscDragView superclass, it is now
  462.         necessary to call [self cleanupAfterDestinationDrag] if you
  463.         stop the drag by returning NO from either prepareForDragOperation:
  464.         or performDragOperation:.
  465.              
  466. ****************************************************************************/
  467.